package cn.luowb.checkchat.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.luowb.checkchat.common.exception.ClientException;
import cn.luowb.checkchat.common.exception.ServiceException;
import cn.luowb.checkchat.common.util.MinioService;
import cn.luowb.checkchat.dao.entity.MediaResourceDO;
import cn.luowb.checkchat.dto.resp.MediaUploadRespDTO;
import cn.luowb.checkchat.service.MediaResourceService;
import cn.luowb.checkchat.service.MediaService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Service
@RequiredArgsConstructor
@Slf4j
public class MediaServiceImpl implements MediaService {

    private final MinioService minioService;
    private final MediaResourceService mediaResourceService;

    // 允许的文件类型
    private static final List<String> ALLOWED_IMAGE_TYPES = Arrays.asList(
            "image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp"
    );
    private static final List<String> ALLOWED_VIDEO_TYPES = Arrays.asList(
            "video/mp4", "video/quicktime", "video/x-msvideo", "video/webm"
    );
    private static final List<String> ALLOWED_AUDIO_TYPES = Arrays.asList(
            "audio/mpeg", "audio/wav", "audio/ogg", "audio/mp4", "audio/webm"
    );

    // 最大文件大小 50MB
    private static final long MAX_FILE_SIZE = 50 * 1024 * 1024;

    @Transactional
    @Override
    public MediaUploadRespDTO uploadMedia(MultipartFile file, String type, String folder, Long userId) {
        // 校验文件
        validateFile(file);

        // 生成文件名
        String filename = generateFilename(file.getOriginalFilename());

        try {
            // 上传文件到MinIO
            String fileUrl = minioService.upload(file, filename, folder);

            // 保存到数据库
            MediaResourceDO mediaResource = new MediaResourceDO();
            mediaResource.setType(determineFileType(file.getContentType(), type));
            mediaResource.setUrl(fileUrl);
            mediaResource.setRefType(folder != null ? folder : "user_upload"); // 使用folder作为ref_type，默认为user_upload
            mediaResource.setRefId(userId); // 关联用户ID
            mediaResource.setCreateTime(LocalDateTime.now());
            mediaResource.setUpdateTime(LocalDateTime.now());

            mediaResourceService.save(mediaResource);

            // 构建响应
            MediaUploadRespDTO response = new MediaUploadRespDTO();
            response.setUrl(fileUrl);
            response.setType(determineFileType(file.getContentType(), type));
            response.setFilename(filename);
            response.setSize(file.getSize());
            response.setMimeType(file.getContentType());

            log.info("用户 {} 文件上传成功: {}", userId, fileUrl);
            return response;

        } catch (Exception e) {
            log.error("用户 {} 文件上传失败: {}", userId, filename, e);
            throw new ServiceException("文件上传失败");
        }
    }

    @Override
    public List<MediaUploadRespDTO> uploadMultipleMedia(MultipartFile[] files, String type, String folder, Long userId) {
        if (files == null || files.length == 0) {
            throw new ClientException("请选择要上传的文件");
        }

        // 检查总文件大小
        long totalSize = 0;
        for (MultipartFile file : files) {
            if (file != null && !file.isEmpty()) {
                totalSize += file.getSize();
                if (totalSize > MAX_FILE_SIZE * files.length) {
                    throw new ClientException("总文件大小不能超过" + (MAX_FILE_SIZE * files.length / 1024 / 1024) + "MB");
                }
            }
        }

        List<MediaUploadRespDTO> results = new ArrayList<>();
        for (int i = 0; i < files.length; i++) {
            MultipartFile file = files[i];
            if (file == null || file.isEmpty()) {
                continue;
            }

            try {
                MediaUploadRespDTO result = uploadMedia(file, type, folder, userId);
                results.add(result);
                log.info("用户 {} 文件上传成功 ({}/{}): {}", userId, i + 1, files.length, result.getUrl());
            } catch (Exception e) {
                log.error("用户 {} 文件上传失败 ({}/{}): {}", userId, i + 1, files.length, file.getOriginalFilename(), e);
                // 可以选择继续上传其他文件
                throw new ServiceException("第" + (i + 1) + "个文件上传失败: " + e.getMessage());
            }
        }

        if (results.isEmpty()) {
            throw new ClientException("没有成功上传任何文件");
        }

        return results;
    }

    /**
     * 校验文件
     */
    private void validateFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new ClientException("文件不能为空");
        }

        // 检查文件大小
        if (file.getSize() > MAX_FILE_SIZE) {
            throw new ClientException("文件大小不能超过50MB");
        }

        // 检查文件类型
        String contentType = file.getContentType();
        if (contentType == null) {
            throw new ClientException("无法识别文件类型");
        }

        boolean isValidType = ALLOWED_IMAGE_TYPES.contains(contentType) ||
                ALLOWED_VIDEO_TYPES.contains(contentType) ||
                ALLOWED_AUDIO_TYPES.contains(contentType);

        if (!isValidType) {
            throw new ClientException("不支持的文件类型: " + contentType +
                    "，支持的类型: jpg, jpeg, png, gif, webp, mp4, mov, avi, webm, mp3, wav, ogg");
        }
    }

    /**
     * 生成文件名
     */
    private String generateFilename(String originalFilename) {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String randomStr = IdUtil.fastSimpleUUID().substring(0, 8);

        String extension = "";
        if (StrUtil.isNotBlank(originalFilename)) {
            int dotIndex = originalFilename.lastIndexOf(".");
            if (dotIndex > 0) {
                extension = originalFilename.substring(dotIndex);
            }
        }

        return timestamp + "_" + randomStr + extension;
    }

    /**
     * 确定文件类型
     */
    private String determineFileType(String contentType, String userSpecifiedType) {
        if (StrUtil.isNotBlank(userSpecifiedType)) {
            return userSpecifiedType;
        }

        if (contentType != null) {
            if (contentType.startsWith("image/")) {
                return "image";
            } else if (contentType.startsWith("video/")) {
                return "video";
            } else if (contentType.startsWith("audio/")) {
                return "audio";
            }
        }

        return "unknown";
    }
}